package com.xuecheng.base.handler;

import com.xuecheng.base.exception.CommonError;
import com.xuecheng.base.result.ErrorResponse;
import com.xuecheng.base.exception.XCPlusBaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * @author 勾新杰
 * @version 1.0
 * @description: 全局异常处理器
 * @date 2024/12/19 21:51
 */
@Slf4j
@RestControllerAdvice // 实际就是mvc对controller的增强，用aop进行增强、扩展，Rest表示返回json格式数据，但是写在base模块里面，需要手动配置能够扫描得到
public class GlobalExceptionHandler {

    /**
     * 处理自定义异常
     *
     * @param e 处理自定义异常
     * @return 错误信息
     */
    @ExceptionHandler(XCPlusBaseException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleException(XCPlusBaseException e) {
        log.error("系统异常:{}", e.getMessage());
        return new ErrorResponse(e.getMessage());
    }

    /**
     * 处理表单参数校验异常，controller层
     *
     * @param e 表单参数校验异常
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleException(MethodArgumentNotValidException e) {
        // 1. 获取错误信息
        StringBuffer errorMsg = new StringBuffer();
        e.getBindingResult().getFieldErrors().forEach(fieldError -> {
            // 1.1 输出错误信息
            log.error("系统异常:{}", fieldError.getDefaultMessage());
            // 1.2 拼接错误信息
            errorMsg.append(fieldError.getDefaultMessage()).append(",");
        });
        // 2. 删除最后一个逗号并返回拼接后的字符串
        errorMsg.deleteCharAt(errorMsg.length() - 1);
        return new ErrorResponse(errorMsg.toString());
    }

    /**
     * 处理表单参数校验异常，service层
     *
     * @param e 表单参数校验异常
     * @return 错误信息
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleException(ConstraintViolationException e) {
        // 1. 获取错误信息
        StringBuffer errorMsg = new StringBuffer();
        e.getConstraintViolations().forEach(constraintViolation -> {
            log.error("系统异常:{}", constraintViolation.getMessage());
            errorMsg.append(constraintViolation.getMessage()).append(",");
        });
        // 2. 删除最后一个逗号并返回拼接后的字符串
        errorMsg.deleteCharAt(errorMsg.length() - 1);
        return new ErrorResponse(errorMsg.toString());
    }

    /**
     * 处理系统异常
     *
     * @param e 系统异常
     * @return 错误信息
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleException(Exception e) {
        log.error("系统异常:{}", e.getMessage());
        if(e.getMessage().equals("不允许访问"))
            return new ErrorResponse(CommonError.HAS_NO_AUTHORITY.getErrMessage());
        return new ErrorResponse(CommonError.UNKNOWN_ERROR.getErrMessage());
    }
}
